#include "MetaCompiler.h"

namespace GxMetaParser
{
	Lexer::Lexer(Grammar * g, const String & profile)
	{
		lexer = new MetaLexer(profile);
		curToken = 0;
		if (!lexer->Errors.Count())
		{
			TokenID.SetSize(lexer->GetRuleCount());
			for (int i=0; i<lexer->GetRuleCount(); i++)
			{
				TokenID[i] = g->RegisterTerminalSymbol(lexer->GetTokenName(i));
			}
		}
		EndSymbolID = g->GetEndSymbolID();
	}

	bool Lexer::CanParse()
	{
		return lexer && !lexer->Errors.Count();
	}

	LexerError & Lexer::GetError(int id)
	{
		return lexer->Errors[id];
	}

	int Lexer::GetErrorCount()
	{
		return lexer->Errors.Count();
	}

	bool Lexer::Parse(const String &str)
	{
		if (CanParse())
		{
			bool rs = false;
			rs = lexer->Parse(str, stream);
			if (rs)
				curToken = stream.Begin();
			return rs;
		}
		else
			return false;
	}

	Token Lexer::GetLastToken()
	{
		Token rs;
		if (curToken && curToken->GetPrevious())
		{
			rs.Position = curToken->GetPrevious()->Data.Position;
			rs.Str = curToken->GetPrevious()->Data.Str;
			rs.Type = curToken->GetPrevious()->Data.TypeID;
		}
		else if (stream.End())
		{
			rs.Position = stream.End()->Data.Position;
			rs.Str = stream.End()->Data.Str;
			rs.Type = stream.End()->Data.TypeID;
		}
		else
			return GetNextToken();
		return rs;
	}

	Token Lexer::GetNextToken()
	{
		Token rs;
		if (curToken)
		{
			rs.Position = curToken->Data.Position;
			rs.Str = curToken->Data.Str;
			rs.Type = TokenID[curToken->Data.TypeID];
		}
		else
		{
			rs.Position = (stream.Count()?stream.End()->Data.Position:0);
			rs.Type = EndSymbolID;
		}
		return rs;
	}

	Token Lexer::ReadNextToken()
	{
		Token rs;
		if (curToken)
		{
			rs.Position = curToken->Data.Position;
			rs.Str = curToken->Data.Str;
			rs.Type = TokenID[curToken->Data.TypeID];
			curToken = curToken->GetNext();
		}
		else
		{
			rs.Position = stream.End()->Data.Position;
			rs.Type = EndSymbolID;
		}
		return rs;
	}
}